<template>
  <div>
    <div id="canvas-container" style="width: 100%; height: 100%;"></div>
  </div>
</template>

<script>
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { TextureLoader, SphereGeometry, MeshBasicMaterial, Mesh } from 'three';

export default {
  name: 'GLTFLoaderExample',
  mounted() {
    this.init();
  },
  methods: {
    init() {
      // 场景、相机、渲染器设置
      const scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 5000);
      //设置渲染器，并添加抗锯齿效果 
      const renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.shadowMap.enabled = false;//关闭场景中的阴影渲染
      renderer.setClearColor(0xFFFFFF, 0); // 设置背景色为白色，alpha为0确保完全不透明
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.getElementById('canvas-container').appendChild(renderer.domElement);

      //设置编码方式和gltf贴图保持一致，解决渲染颜色偏差的问题
      renderer.outputEncoding = THREE.sRGBEncoding;

      // 创建一个三维坐标轴
      //const axesHelper = new THREE.AxesHelper(800);
      // 坐标轴对象添加到三维场景中
      //scene.add(axesHelper);

      // 照明
      const ambientLight = new THREE.AmbientLight(0xffffff, 3); // 平行光
      scene.add(ambientLight);

      // 添加光源
      const directionalLight = new THREE.DirectionalLight(0xffffff, 4); // 方向光颜色和强度
      directionalLight.position.set(1, 1, 1).normalize(); // 调整光源方向
      directionalLight.castShadow = false;  // 光源投射阴影
      directionalLight.shadow.bias = -0.001; // 调整偏移值，负值减少正面阴影闪烁，正值减少背面阴影
      // 增加阴影分辨率
      directionalLight.shadow.mapSize.width = 2048;
      directionalLight.shadow.mapSize.height = 2048;

      // 调整阴影偏移量
      directionalLight.shadow.camera.left = -1000;
      directionalLight.shadow.camera.right = 1000;
      directionalLight.shadow.camera.top = 1000;
      directionalLight.shadow.camera.bottom = -1000;
      scene.add(directionalLight);

      // 添加半球光源，模拟天空和地面的反射光，增加真实感
      const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 6); // 第三个参数是强度
      hemisphereLight.position.set(0, 20, 0); // 可以调整光源的位置以改变效果
      scene.add(hemisphereLight);

      //天空背景图 创建和加载纹理
      const textureLoader = new TextureLoader();
      //texture 是通过 TextureLoader 的 load 方法加载全景图像纹理后，传递给回调函数的参数。
      textureLoader.load('https://img.zcool.cn/community/0385a8855deb81f00000159952cfa85.jpg', function (texture) {
        // 创建全景球体
        const sphereGeometry = new SphereGeometry(2000);
        // 翻转面的方向，使得贴图在球体的内部
        sphereGeometry.scale(-1, 1, 1);

        // 创建材料并将全景图的纹理应用到上面
        const sphereMaterial = new MeshBasicMaterial({ map: texture });

        // 创建网格对象并将其添加到场景中
        const sphere = new Mesh(sphereGeometry, sphereMaterial);
        scene.add(sphere);
      });

      // 添加鼠标控制器 
      const controls = new OrbitControls(camera, renderer.domElement);
      this.controls = controls;
      controls.enableDamping = true; // 允许阻尼效果，使动画更平滑
      controls.rotateSpeed = 0.2; // 旋转速度
      controls.dampingFactor = 0.25; // 阻尼因子
      controls.screenSpacePanning = false; // 禁止屏幕空间平移
      // 设置最小缩放距离
      controls.minDistance = 320; // 例如，最小距离为1单位
      // 设置最大缩放距离
      controls.maxDistance = 1150; // 例如，最大距离为100单位

      // 加载GLB模型
      const dracoLoader = new DRACOLoader();
      dracoLoader.setDecoderPath('draco/gltf/');
      dracoLoader.setDecoderConfig({ type: 'js' });
      dracoLoader.preload();
      const loader = new GLTFLoader();
      loader.setDRACOLoader(dracoLoader);
      loader.load("glbmodel/2024110.glb", (gltf) => {
        const model = gltf.scene;
        model.traverse((child) => {
          //动态获取模型中心点，并设置模型的旋转中心点target.set
          if (child instanceof THREE.Mesh && child.name === "系统嵌板1_-_玻璃-2195145-_三维_-_Administrator__2feecad") {
            child.material.side = THREE.DoubleSide;//模型双面渲染
            model.scale.set(1, 1, 1);  //设置模型大小缩放
            model.position.set(-65, 0, 0);//设置模型的位置
            camera.position.set(484, 100, -250); //设置相机的位置
            controls.target.set(child.position.x, child.position.y, child.position.z);//设置模型的旋转中心点
            camera.lookAt(child.position.x, child.position.y, child.position.z);//使相机看向指定的点


            // 防止透明材质背面因alphaTest或transparent设置不当导致的阴影错觉
            if (child.material.transparent) {
              child.material.alphaTest = 0.1; // 或者确保transparent为true且设置了正确的alpha值
            }
            child.geometry.computeVertexNormals();// 模型的法线方向错误也可能导致光照计算不正确，使得某些面看起来比其他面更暗。可以尝试重新计算法线
            child.geometry.normalsNeedUpdate = true;
          }
        });

        // 渲染循环
        const animate = () => {
          // 假设你的3D模型引用是'myModel'，这里打印模型的位置

          requestAnimationFrame(animate);
          //model.rotation.y += 0.01; // 让模型旋转起来
          renderer.render(scene, camera);
        };
        animate();
        scene.add(model);
      }, undefined, (error) => {
        console.error('An error happened loading the model:', error);
      });
    }
  }
};
</script>